package top.luo;

import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 一致性hash, 带有虚拟节点
 *
 * @author luo
 */
public class ConsistentHashWithVirtualNode {

    public static void main(String[] args) {
        // 每个节点的虚拟节点格式
        int virtualNodeNum = 5;

        // 初始化, 将节点hash映射到hash环上
        SortedMap<Integer, String> nodeMap = new TreeMap<>();
        String[] nodeArr = new String[]{"11.11.11.11", "22.22.22.22"};
        for (String node : nodeArr) {
            int nodeHash = Math.abs(node.hashCode());
            nodeMap.put(nodeHash, node);

            // 虚拟节点处理
            for (int i = 0; i < virtualNodeNum; i++) {
                int virtualHash = (node + "#" + i).hashCode();
                nodeMap.put(virtualHash, node + "#" + i);
            }
        }

        // 客户端hash处理
        String[] clientArr = new String[]{"123.234.222.233", "147.12.23.3", "13.31.56.2", "10.22.34.56", "14.67.254.255", "10.2.2.1", "123.23.31.24"};
        for (String client : clientArr) {
            int clientHash = Math.abs(client.hashCode());
            // 顺时针最近的节点
            SortedMap<Integer, String> tailMap = nodeMap.tailMap(clientHash);
            // 可能为空, 取环中的第一个节点
            if (tailMap.isEmpty()) {
                Integer nodeIndex = nodeMap.firstKey();
                System.out.println("client: " + client + "\t" + "node: " + nodeMap.get(nodeIndex));
            } else {
                Integer nodeIndex = tailMap.firstKey();
                System.out.println("client: " + client + "\t" + "node: " + nodeMap.get(nodeIndex));
            }
        }
    }

}
